home *** CD-ROM | disk | FTP | other *** search
/ EnigmA Amiga Run 1995 October / EnigmA AMIGA RUN 01 (1995)(G.R. Edizioni)(IT)[!][issue 1995-10][Aminet 7].iso / Aminet / dev / gui / BGUI11c.lha / ARexxClass / ARexxClass.c < prev    next >
C/C++ Source or Header  |  1995-04-23  |  37KB  |  1,011 lines

  1. /*
  2. **             File: arexxclass.c
  3. **      Description: BOOPSI ARexx interface class.
  4. **        Copyright: (C) Copyright 1994-1995 Jaba Development.
  5. **                   (C) Copyright 1994-1995 Jan van den Baard.
  6. **                   All Rights Reserved.
  7. **/
  8.  
  9. /*
  10. **      Uncomment the following line if you want the
  11. **      class to use memory pools and you have got
  12. **      the 3.1 amiga.lib. You need the 3.1 amiga.lib
  13. **      because the earlier version do not contain
  14. **      link versions of the pool routines.
  15. **/
  16.  
  17. /* #define POOLS */
  18.  
  19. /*
  20. **      When POOLS is defined the class will
  21. **      use the allocation routines as defined
  22. **      in the source. Otherwise it simply
  23. **      allocates memory from the system pool.
  24. **/
  25. #ifdef POOLS
  26. #define AllocMemory(s)          GetMem( ad, s )
  27. #define FreeMemory(p)           PutMem( ad, p )
  28. #else
  29. #define AllocMemory(s)          AllocVec( s, MEMF_PUBLIC | MEMF_CLEAR )
  30. #define FreeMemory(p)           FreeVec( p )
  31. #endif
  32.  
  33. /*
  34. **      Include necessary headers.
  35. **/
  36. #include "ARexxClass.h"
  37.  
  38. #include <proto/intuition.h>
  39. #include <proto/utility.h>
  40. #include <proto/rexxsyslib.h>
  41. #include <proto/exec.h>
  42. #include <proto/dos.h>
  43.  
  44. #include <clib/alib_protos.h>
  45.  
  46. #include <stdio.h>
  47. #include <string.h>
  48. #include <ctype.h>
  49.  
  50. /*
  51. **      Compiler crap. Should compile under SAS this way...
  52. **/
  53. #ifdef _DCC
  54. #define SAVEDS __geta4
  55. #define ASM
  56. #define REG(x) __ ## x
  57. #else
  58. #define SAVEDS __saveds
  59. #define ASM __asm
  60. #define REG(x) register __ ## x
  61. #endif
  62.  
  63. /*
  64. **      Object instance data. Every object
  65. **      created from this class has this
  66. **      data.
  67. **/
  68. typedef struct {
  69.         struct MsgPort                  *ad_Port;       /* Host message port.         */
  70.         UBYTE                           *ad_HostName;   /* Host name.                 */
  71.         UBYTE                           *ad_FileExt;    /* File extention.            */
  72.         ULONG                            ad_PendCnt;    /* Messages still un-reply'd. */
  73.         REXXCOMMAND                     *ad_Commands;   /* Host command list.         */
  74.         struct RDArgs                   *ad_DOSParser;  /* ReadArgs() parser.         */
  75.         UWORD                            ad_Flags;      /* See below.                 */
  76. #ifdef POOLS
  77.         APTR                             ad_MemPool;    /* Memory pool.               */
  78. #endif
  79. } AD;
  80.  
  81. /*
  82. **      Static module prototypes of functions
  83. **      defined after they are referenced.
  84. **/
  85. STATIC ULONG SAVEDS ASM ARexxDispatch( REG(A0) Class *cl, REG(A2) Object *obj, REG(A1) Msg );
  86.  
  87. /*
  88. **      Class initialization. Simply creates the
  89. **      class and set's up the dispatcher.
  90. **/
  91. Class *InitARexxClass( void )
  92. {
  93.         Class                   *cl;
  94.  
  95.         if ( cl = MakeClass( NULL, ROOTCLASS, NULL, sizeof( AD ), 0L ))
  96.                 cl->cl_Dispatcher.h_Entry = (HOOKFUNC)ARexxDispatch;
  97.  
  98.         return( cl );
  99. }
  100.  
  101. /*
  102. **      Free the class. A simply FreeClass()
  103. **      would suffice but in the future this
  104. **      may do more.
  105. **/
  106. BOOL FreeARexxClass( Class *cl )
  107. {
  108.         return( FreeClass( cl ));
  109. }
  110.  
  111. /*
  112. **      These routines are only compiled when
  113. **      POOLS is defined. In that case the memory
  114. **      allocations are done in the object it's
  115. **      memory pool.
  116. **/
  117. #ifdef POOLS
  118. /*
  119. **      Pool allocation.
  120. **/
  121. STATIC APTR GetMem( AD *ad, ULONG size )
  122. {
  123.         ULONG                   *ptr;
  124.  
  125.         /*
  126.         **      Allocate the memory. Size is tracked so we do not
  127.         **      need to remember it when deallocating the memory again.
  128.         **/
  129.         if ( ptr = LibAllocPooled( ad->ad_MemPool, size + sizeof( ULONG ))) {
  130.                 /*
  131.                 **      Store allocation size.
  132.                 **/
  133.                 *ptr = size + sizeof( ULONG );
  134.                 /*
  135.                 **      Adjust pointer.
  136.                 **/
  137.                 ptr++;
  138.         }
  139.         return(( APTR )ptr );
  140. }
  141.  
  142. /*
  143. **      Pool freeing.
  144. **/
  145. STATIC VOID PutMem( AD *ad, APTR mem )
  146. {
  147.         ULONG                   *ptr = ( ULONG * )mem;
  148.  
  149.         /*
  150.         **      Retrieve the original allocation.
  151.         **/
  152.         ptr--;
  153.  
  154.         /*
  155.         **      Deallocate.
  156.         **/
  157.         LibFreePooled( ad->ad_MemPool, ptr, *ptr );
  158. }
  159. #endif
  160.  
  161. /*
  162. **      Duplicate a string.
  163. **/
  164. STATIC UBYTE *DupStr( AD *ad, UBYTE *str )
  165. {
  166.         UBYTE                   *dup = AllocMemory( strlen( str ) + 1 );
  167.  
  168.         /*
  169.         **      Allocation OK?
  170.         **/
  171.         if ( dup )
  172.                 /*
  173.                 **      Copy the string.
  174.                 **/
  175.                 strcpy( dup, str );
  176.  
  177.         return( dup );
  178. }
  179.  
  180. /*
  181. **      Reply a rexx command.
  182. **/
  183. STATIC VOID ReplyRexxCommand( struct RexxMsg *rxm, LONG prim, LONG sec, UBYTE *res )
  184. {
  185.         UBYTE           buf[ 16 ];
  186.  
  187.         /*
  188.         **      Result wanted?
  189.         **/
  190.         if ( rxm->rm_Action & RXFF_RESULT ) {
  191.                 /*
  192.                 **      Primary result?
  193.                 **/
  194.                 if ( ! prim ) {
  195.                         /*
  196.                         **      We setup the secondary result to
  197.                         **      the result string when one was passed.
  198.                         **/
  199.                         sec = res ? ( LONG )CreateArgstring( res, strlen( res )) : 0L;
  200.                 } else {
  201.                         /*
  202.                         **      Primary result bigger than 0?
  203.                         **/
  204.                         if ( prim > 0 ) {
  205.                                 /*
  206.                                 **      Setup the result field
  207.                                 **      to point to a string containing
  208.                                 **      the secondary result number.
  209.                                 **/
  210.                                 sprintf( buf, "%ld", sec );
  211.                                 res = buf;
  212.                         } else {
  213.                                 /*
  214.                                 **      Negate primary result and
  215.                                 **      setup the result field to
  216.                                 **      the secondary result.
  217.                                 **/
  218.                                 prim = -prim;
  219.                                 res = ( UBYTE * )sec;
  220.                         }
  221.  
  222.                         /*
  223.                         **      Setup ARexx it's "RC2" variable to
  224.                         **      the result.
  225.                         **/
  226.                         SetRexxVar(( struct Message * )rxm, "RC2", res, strlen( res ));
  227.  
  228.                         /*
  229.                         **      Clear secondary result.
  230.                         **/
  231.                         sec = 0L;
  232.                 }
  233.         } else if ( prim < 0 )
  234.                 /*
  235.                 **      Negate primary result.
  236.                 **/
  237.                 prim = -prim;
  238.  
  239.         /*
  240.         **      Setup result fields.
  241.         **/
  242.         rxm->rm_Result1 = prim;
  243.         rxm->rm_Result2 = sec;
  244.  
  245.         /*
  246.         **      Reply the RexxMsg.
  247.         **/
  248.         ReplyMsg(( struct Message * )rxm );
  249. }
  250.  
  251. /*
  252. **      Free a RexxMsg command.
  253. **/
  254. STATIC VOID FreeRexxCommand( struct RexxMsg *rxm )
  255. {
  256.         /*
  257.         **      Delete the result Argstring.
  258.         **/
  259.         if ( ! rxm->rm_Result1 && rxm->rm_Result2 )
  260.                 DeleteArgstring(( UBYTE * )rxm->rm_Result2 );
  261.  
  262.         /*
  263.         **      Close input handle.
  264.         **/
  265.         if ( rxm->rm_Stdin && rxm->rm_Stdin != Input()) {
  266.                 /*
  267.                 **      If the output handle is the
  268.                 **      same as the input handle we
  269.                 **      can safely clear it.
  270.                 **/
  271.                 if ( rxm->rm_Stdout == rxm->rm_Stdin )
  272.                         rxm->rm_Stdout = NULL;
  273.                 Close( rxm->rm_Stdin );
  274.                 rxm->rm_Stdin = NULL;
  275.         }
  276.  
  277.         /*
  278.         **      Close output handle if it is not
  279.         **      the same as Stdin.
  280.         **/
  281.         if ( rxm->rm_Stdout && rxm->rm_Stdout != Output()) {
  282.                 Close( rxm->rm_Stdout );
  283.                 rxm->rm_Stdout = NULL;
  284.         }
  285.  
  286.         /*
  287.         **      Delete the command Argstring.
  288.         **/
  289.         DeleteArgstring(( UBYTE * )ARG0( rxm ));
  290.         /*
  291.         **      Delete the message itself.
  292.         **/
  293.         DeleteRexxMsg( rxm );
  294. }
  295.  
  296. /*
  297. **      Create a RexxMsg command.
  298. **/
  299. STATIC struct RexxMsg *CreateRexxCommand( AD *ad, UBYTE *comname, BPTR handle )
  300. {
  301.         struct RexxMsg                  *rxm;
  302.  
  303.         /*
  304.         **      Create the RexxMsg.
  305.         **/
  306.         if ( rxm = CreateRexxMsg( ad->ad_Port, ad->ad_FileExt, ad->ad_HostName )) {
  307.                 /*
  308.                 **      Create the Argstring.
  309.                 **/
  310.                 if ( rxm->rm_Args[ 0 ] = CreateArgstring( comname, strlen( comname ))) {
  311.                         /*
  312.                         **      Setup action flags.
  313.                         **/
  314.                         rxm->rm_Action = RXCOMM | RXFF_RESULT;
  315.                         /*
  316.                         **      Setup file handles.
  317.                         **/
  318.                         rxm->rm_Stdin  = rxm->rm_Stdout = handle;
  319.                         return( rxm );
  320.                 }
  321.                 /*
  322.                 **      Argstring creation failed.
  323.                 **/
  324.                 DeleteRexxMsg( rxm );
  325.         }
  326.         return( NULL );
  327. }
  328.  
  329. /*
  330. **      Send a RexxMsg command to the
  331. **      ARexx server.
  332. **/
  333. STATIC struct RexxMsg *CommandToRexx( AD *ad, struct RexxMsg *rxm )
  334. {
  335.         struct MsgPort          *rxp;
  336.  
  337.         /*
  338.         **      Try to find the "REXX"
  339.         **      message port.
  340.         **/
  341.         Forbid();
  342.  
  343.         if ( ! ( rxp = FindPort( RXSDIR ))) {
  344.                 /*
  345.                 **      Oops. ARexx server
  346.                 **      not active.
  347.                 **/
  348.                 Permit();
  349.                 return( NULL );
  350.         }
  351.  
  352.         /*
  353.         **      Send off the message.
  354.         **/
  355.         PutMsg( rxp, &rxm->rm_Node );
  356.  
  357.         Permit();
  358.  
  359.         /*
  360.         **      Increase pending counter.
  361.         **/
  362.         ad->ad_PendCnt++;
  363.  
  364.         return( rxm );
  365. }
  366.  
  367. /*
  368. **      Send a command to the ARexx server.
  369. **/
  370. STATIC struct RexxMsg *SendRexxCommand( AD *ad, UBYTE *comname, BPTR handle )
  371. {
  372.         struct RexxMsg                  *rxm;
  373.  
  374.         /*
  375.         **      Create a RexxMsg command and
  376.         **      send it off to the ARexx server.
  377.         **/
  378.         if ( rxm = CreateRexxCommand( ad, comname, handle ))
  379.                 return( CommandToRexx( ad, rxm ));
  380.  
  381.         return( NULL );
  382. }
  383.  
  384. STATIC REXXCOMMAND *FindRXCommand( AD *ad, UBYTE *comname, UWORD len )
  385. {
  386.         REXXCOMMAND             *rc = ad->ad_Commands;
  387.  
  388.         while ( rc->rc_Func ) {
  389.                 if ( ! strnicmp( comname, rc->rc_Name, len ) && isspace( comname[ strlen( rc->rc_Name ) ] ))
  390.                         return( rc );
  391.                 rc++;
  392.         }
  393.  
  394.         return( NULL );
  395. }
  396.  
  397. /*
  398. **      Execute a command.
  399. **/
  400. STATIC VOID DoRXCommand( AD *ad, struct RexxMsg *rxm )
  401. {
  402.         struct RexxMsg                  *rm;
  403.         REXXCOMMAND                     *rco;
  404.         REXXARGS                        *ra;
  405.         UBYTE                           *comname, *args, *tmp, *result = NULL;
  406.         LONG                             rc = 20, rc2 = 0;
  407.         UWORD                            numargs = 0, len = 0;
  408.  
  409.         /*
  410.         **      Allocate memory for the command
  411.         **      name and it's argument string.
  412.         **/
  413.         if ( ! ( comname = ( UBYTE * )AllocMemory( strlen(( UBYTE * )ARG0( rxm )) + 2 ))) {
  414.                 rc2 = ERROR_NO_FREE_STORE;
  415.                 return;
  416.         }
  417.  
  418.         /*
  419.         **      Copy command name and argument string.
  420.         **/
  421.         strcpy( comname, ( UBYTE * )ARG0( rxm ));
  422.  
  423.         /*
  424.         **      ReadArgs() requires the argument
  425.         **      string to end with a newline.
  426.         **/
  427.         strcat( comname, "\n" );
  428.  
  429.         /*
  430.         **      Find the length of the command
  431.         **      the start of the arguments.
  432.         **/
  433.         args = comname;
  434.         while ( isspace( *args )) args++;
  435.         tmp  = args;
  436.         while ( ! isspace( *args )) { len++; args++; }
  437.  
  438.         /*
  439.         **      Find the command.
  440.         **/
  441.         if ( rco = FindRXCommand( ad, tmp, len )) {
  442.                 /*
  443.                 **      Allocate REXXARGS structure.
  444.                 **/
  445.                 if ( ra = ( REXXARGS * )AllocMemory( sizeof( REXXARGS ))) {
  446.                         /*
  447.                         **      Count number of expected args.
  448.                         **/
  449.                         if ( rco->rc_ArgTemplate ) {
  450.                                 tmp = rco->rc_ArgTemplate;
  451.                                 while ( *tmp != '\n' ) {
  452.                                         if ( *tmp++ == ',' ) numargs++;
  453.                                 }
  454.                                 numargs++;
  455.                                 /*
  456.                                 **      Allocate arg array.
  457.                                 **/
  458.                                 if ( ra->ra_ArgList = ( ULONG * )AllocMemory( numargs * sizeof( ULONG ))) {
  459.                                         /*
  460.                                         **      Setup RDArgs.
  461.                                         **/
  462.                                         ad->ad_DOSParser->RDA_Source.CS_Buffer = args;
  463.                                         ad->ad_DOSParser->RDA_Source.CS_Length = strlen( args );
  464.                                         ad->ad_DOSParser->RDA_Source.CS_CurChr = 0;
  465.                                         ad->ad_DOSParser->RDA_DAList           = NULL;
  466.                                         ad->ad_DOSParser->RDA_Buffer           = NULL;
  467.                                         /*
  468.                                         **      Parse args.
  469.                                         **/
  470.                                         if ( ReadArgs( rco->rc_ArgTemplate, ra->ra_ArgList, ad->ad_DOSParser )) {
  471.                                                 /*
  472.                                                 **      Call the REXX routine.
  473.                                                 **/
  474.                                                 ( rco->rc_Func )( ra, rxm );
  475.  
  476.                                                 rc     = ra->ra_RC;
  477.                                                 rc2    = ra->ra_RC2;
  478.                                                 result = ra->ra_Result;
  479.  
  480.                                                 FreeArgs( ad->ad_DOSParser );
  481.                                         } else {
  482.                                                 rc = 10;
  483.                                                 rc2 = IoErr();
  484.                                         }
  485.                                         FreeMemory( ra->ra_ArgList );
  486.                                 } else
  487.                                         rc2 = ERROR_NO_FREE_STORE;
  488.                         } else {
  489.                                 /*
  490.                                 **      No args.
  491.                                 **/
  492.                                 ( rco->rc_Func )( ra, rxm );
  493.  
  494.                                 rc     = ra->ra_RC;
  495.                                 rc2    = ra->ra_RC2;
  496.                                 result = ra->ra_Result;
  497.                         }
  498.                         FreeMemory( ra );
  499.                 } else
  500.                         rc2 = ERROR_NO_FREE_STORE;
  501.         } else {
  502.                 /*
  503.                 **      Not found in our list?
  504.                 **      Maybe it's a script.
  505.                 **/
  506.                 if ( rm = CreateRexxCommand( ad, ( UBYTE * )ARG0( rxm ), NULL )) {
  507.                         /*
  508.                         **      Save original message.
  509.                         **/
  510.                         rm->rm_Args[ 15 ] = ( STRPTR )rxm;
  511.                         /*
  512.                         **      Let the REXX server see what
  513.                         **      it can do with this.
  514.                         **/
  515.                         if ( ! CommandToRexx( ad, rm ))
  516.                                 rc2 = ERROR_NOT_IMPLEMENTED;
  517.                 } else
  518.                         rc2 = ERROR_NO_FREE_STORE;
  519.  
  520.                 goto byeBye;
  521.         }
  522.  
  523.         ReplyRexxCommand( rxm, rc, rc2, result );
  524.  
  525.         byeBye:
  526.  
  527.         FreeMemory( comname );
  528. }
  529.  
  530. /*
  531. **      OM_NEW.
  532. **/
  533. STATIC ULONG ARexxNew( Class *cl, Object *obj, struct opSet *ops )
  534. {
  535.         struct TagItem         *attr = ops->ops_AttrList, *tag;
  536.         struct MsgPort         *mp;
  537.         AD                     *ad;
  538.         ULONG                   rc, *ecode, ext = 1L;
  539.         UBYTE                   unique_name[ 80 ], *tmp;
  540.  
  541.         /*
  542.         **      Let the superclass set us up...
  543.         **/
  544.         if ( rc = ( ULONG )DoSuperMethodA( cl, obj, ( Msg )ops )) {
  545.                 /*
  546.                 **      Get the instance data.
  547.                 **/
  548.                 ad = ( AD * )INST_DATA( cl, rc );
  549.                 /*
  550.                 **      Safety precautions.
  551.                 **/
  552.                 bzero(( char * )ad, sizeof( AD ));
  553.  
  554.                 /*
  555.                 **      First see if we got error storage.
  556.                 **/
  557.                 if ( tag = FindTagItem( AC_ErrorCode, attr ))
  558.                         ecode = ( ULONG * )tag->ti_Data;
  559.  
  560. #ifdef POOLS
  561.                 /*
  562.                 **      Create a memory pool.
  563.                 **/
  564.                 if ( ad->ad_MemPool = LibCreatePool( MEMF_PUBLIC | MEMF_CLEAR, 4096L, 4096L )) {
  565. #endif
  566.                 /*
  567.                 **      Create port if a
  568.                 **      host name is supplied.
  569.                 **/
  570.                 if ( tag = FindTagItem( AC_HostName, attr )) {
  571.                         /*
  572.                         **      Store host name.
  573.                         **/
  574.                         ad->ad_HostName = ( UBYTE * )tag->ti_Data;
  575.                         /*
  576.                         **      Name valid?
  577.                         **/
  578.                         if ( ad->ad_HostName && *ad->ad_HostName ) {
  579.                                 /*
  580.                                 **      Make the name unique.
  581.                                 **/
  582.                                 sprintf( unique_name, "%s.1", ad->ad_HostName );
  583.                                 Forbid();
  584.                                 while (( mp = FindPort( unique_name )) && ext <= 99 )
  585.                                         sprintf( unique_name, "%s.%ld", ad->ad_HostName, ++ext );
  586.                                 Permit();
  587.                                 /*
  588.                                 **      Name unique?
  589.                                 **/
  590.                                 if ( ! mp ) {
  591.                                         /*
  592.                                         **      Copy the name.
  593.                                         **/
  594.                                         if ( ad->ad_HostName = DupStr( ad, unique_name )) {
  595.                                                 /*
  596.                                                 **      Uppercase it.
  597.                                                 **/
  598.                                                 tmp = ad->ad_HostName;
  599.                                                 while ( *tmp ) {
  600.                                                         *tmp = toupper( *tmp );
  601.                                                         tmp++;
  602.                                                 }
  603.                                                 /*
  604.                                                 **      Create the port.
  605.                                                 **/
  606.                                                 if ( ad->ad_Port = CreateMsgPort()) {
  607.                                                         /*
  608.                                                         **      Initialize and add the port.
  609.                                                         **/
  610.                                                         ad->ad_Port->mp_Node.ln_Name = ad->ad_HostName;
  611.                                                         ad->ad_Port->mp_Node.ln_Pri  = 0;
  612.                                                         AddPort( ad->ad_Port );
  613.                                                 } else if ( ecode )
  614.                                                         *ecode = RXERR_OUT_OF_MEMORY;
  615.                                         } else if ( ecode )
  616.                                                 *ecode = RXERR_OUT_OF_MEMORY;
  617.                                 } else if ( ecode )
  618.                                         *ecode = RXERR_PORT_ALREADY_EXISTS;
  619.                         } else if ( ecode )
  620.                                 *ecode = RXERR_NO_PORT_NAME;
  621.                 } else if ( ecode )
  622.                         *ecode = RXERR_NO_PORT_NAME;
  623.  
  624.                 /*
  625.                 **      Do we have a port now?
  626.                 **/
  627.                 if ( ad->ad_Port ) {
  628.                         /*
  629.                         **      Find the commandlist.
  630.                         **/
  631.                         if ( tag = FindTagItem( AC_CommandList, attr )) {
  632.                                 if ( ad->ad_Commands = ( REXXCOMMAND * )tag->ti_Data ) {
  633.                                         /*
  634.                                         **      Setup the AmigaDOS parser.
  635.                                         **/
  636.                                         if ( ad->ad_DOSParser = ( struct RDArgs * )AllocDosObject( DOS_RDARGS, NULL )) {
  637.                                                 ad->ad_DOSParser->RDA_Flags = RDAF_NOPROMPT;
  638.                                                 /*
  639.                                                 **      Obtain file extention.
  640.                                                 **/
  641.                                                 if ( tag = FindTagItem( AC_FileExtention, attr ))
  642.                                                         ad->ad_FileExt = ( UBYTE * )tag->ti_Data;
  643.                                                 else
  644.                                                         ad->ad_FileExt = "rexx";
  645.                                                 return( rc );
  646.                                         } else if ( ecode )
  647.                                                 *ecode = RXERR_OUT_OF_MEMORY;
  648.                                 } else if ( ecode )
  649.                                         *ecode = RXERR_NO_COMMAND_LIST;
  650.                         } else if ( ecode )
  651.                                 *ecode = RXERR_NO_COMMAND_LIST;
  652.                 }
  653. #ifdef POOLS
  654.                 } else if ( ecode )
  655.                         *ecode = RXERR_OUT_OF_MEMORY;
  656. #endif
  657.                 /*
  658.                 **      Bliep error...bliep....
  659.                 **/
  660.                 CoerceMethod( cl, ( Object * )rc, OM_DISPOSE );
  661.         }
  662.         return( 0L );
  663. }
  664.  
  665. /*
  666. **      OM_DISPOSE.
  667. **/
  668. STATIC ULONG ARexxDispose( Class *cl, Object *obj, Msg msg )
  669. {
  670.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  671.         struct RexxMsg          *rxm;
  672.  
  673.         /*
  674.         **      Do we have a port?
  675.         **/
  676.         if ( ad->ad_Port ) {
  677.                 /*
  678.                 **      Remove the port from the public list
  679.                 **/
  680.                 RemPort( ad->ad_Port );
  681.                 /*
  682.                 **      Wait for and handle all
  683.                 **      messages still pending.
  684.                 **/
  685.                 if ( ad->ad_PendCnt ) {
  686.                         while ( ad->ad_PendCnt ) {
  687.                                 /*
  688.                                 **      Wait for a message.
  689.                                 **/
  690.                                 WaitPort( ad->ad_Port );
  691.                                 /*
  692.                                 **      Get messages.
  693.                                 **/
  694.                                 while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port )) {
  695.                                         /*
  696.                                         **      Replyed message?
  697.                                         **/
  698.                                         if ( rxm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
  699.                                                 /*
  700.                                                 **      Free the message and decrease the
  701.                                                 **      pending counter.
  702.                                                 **/
  703.                                                 FreeRexxCommand( rxm );
  704.                                                 ad->ad_PendCnt--;
  705.                                         } else
  706.                                                 /*
  707.                                                 **      Tell'm where getting out of here.
  708.                                                 **/
  709.                                                 ReplyRexxCommand( rxm, -20, ( LONG )"Host object closing down", NULL );
  710.                                 }
  711.                         }
  712.                 } else {
  713.                         /*
  714.                         **      In case there are no messages pending we
  715.                         **      still need to reply all that is waiting at
  716.                         **      the port.
  717.                         **/
  718.                         while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port ))
  719.                                 ReplyRexxCommand( rxm, -20, ( LONG )"Host object closing down", NULL );
  720.                 }
  721.  
  722.                 /*
  723.                 **      Delete the port.
  724.                 **/
  725.                 DeleteMsgPort( ad->ad_Port );
  726.         }
  727.  
  728.         /*
  729.         **      Delete the AmigaDOS parser.
  730.         **/
  731.         if ( ad->ad_DOSParser )
  732.                 FreeDosObject( DOS_RDARGS, ad->ad_DOSParser );
  733.  
  734.         /*
  735.         **      Delete the port name.
  736.         **/
  737.         if ( ad->ad_HostName )
  738.                 FreeMemory( ad->ad_HostName );
  739.  
  740. #ifdef POOLS
  741.         /*
  742.         **      Free the pool.
  743.         **/
  744.         LibDeletePool( ad->ad_MemPool );
  745. #endif
  746.  
  747.         /*
  748.         **      Let the superclass do the rest.
  749.         **/
  750.         return( DoSuperMethodA( cl, obj, msg ));
  751. }
  752.  
  753. /*
  754. **      ACM_EXECUTE.
  755. **/
  756. STATIC ULONG ARexxExecute( Class *cl, Object *obj, struct acmExecute *acme )
  757. {
  758.         AD                              *ad = ( AD * )INST_DATA( cl, obj );
  759.         REXXCOMMAND                     *rco;
  760.         REXXARGS                        *ra;
  761.         struct RexxMsg                  *rxm;
  762.         UBYTE                           *args, *tmp, *result = NULL, *com;
  763.         UWORD                            numargs = 0, len = 0;
  764.         ULONG                            r = 20, r2;
  765.  
  766.         /*
  767.         **      Allocate a private copy of the command string.
  768.         **/
  769.         if ( com = ( UBYTE * )AllocMemory( strlen( acme->acme_CommandString ) + 2 )) {
  770.                 /*
  771.                 **      Make a copy terminated with a newline.
  772.                 **/
  773.                 strcpy( com, acme->acme_CommandString );
  774.                 strcat( com, "\n" );
  775.                 /*
  776.                 **      Find the length of the command
  777.                 **      and the start of the arguments.
  778.                 **/
  779.                 args = com;
  780.                 while ( isspace( *args ))   args++;
  781.                 tmp = args;
  782.                 while ( ! isspace( *args )) { len++; args++; }
  783.                 /*
  784.                 **      Look up the command.
  785.                 **/
  786.                 if ( rco = FindRXCommand( ad, tmp, len )) {
  787.                         /*
  788.                         **      Allocate a REXXARGS structure.
  789.                         **/
  790.                         if ( ra = ( REXXARGS * )AllocMemory( sizeof( REXXARGS ))) {
  791.                                 /*
  792.                                 **      Args expected?
  793.                                 **/
  794.                                 if ( rco->rc_ArgTemplate ) {
  795.                                         /*
  796.                                         **      Count the expected number of arguments.
  797.                                         **/
  798.                                         tmp = rco->rc_ArgTemplate;
  799.                                         while ( *tmp != '\n' ) {
  800.                                                 if ( *tmp++ != ',' ) numargs++;
  801.                                         }
  802.                                         numargs++;
  803.                                         /*
  804.                                         **      Allocate space to parse the args.
  805.                                         **/
  806.                                         if ( ra->ra_ArgList = ( ULONG * )AllocMemory( numargs * sizeof( ULONG ))) {
  807.                                                 /*
  808.                                                 **      Setup the parser.
  809.                                                 **/
  810.                                                 ad->ad_DOSParser->RDA_Source.CS_Buffer = args;
  811.                                                 ad->ad_DOSParser->RDA_Source.CS_Length = strlen( args );
  812.                                                 ad->ad_DOSParser->RDA_Source.CS_CurChr = 0;
  813.                                                 ad->ad_DOSParser->RDA_DAList           = NULL;
  814.                                                 ad->ad_DOSParser->RDA_Buffer           = NULL;
  815.                                                 /*
  816.                                                 **      Parse the args.
  817.                                                 **/
  818.                                                 if ( ReadArgs( rco->rc_ArgTemplate, ra->ra_ArgList, ad->ad_DOSParser )) {
  819.                                                         /*
  820.                                                         **      Run command.
  821.                                                         **/
  822.                                                         ( rco->rc_Func )( ra, NULL );
  823.                                                         /*
  824.                                                         **      Store results.
  825.                                                         **/
  826.                                                         r      = ra->ra_RC;
  827.                                                         r2     = ra->ra_RC2;
  828.                                                         result = ra->ra_Result;
  829.                                                         FreeArgs( ad->ad_DOSParser );
  830.                                                 } else {
  831.                                                         r  = 10;
  832.                                                         r2 = IoErr();
  833.                                                 }
  834.                                                 /*
  835.                                                 **      Deallocate arg list.
  836.                                                 **/
  837.                                                 FreeMemory( ra->ra_ArgList );
  838.                                         } else
  839.                                                 r2 = ERROR_NO_FREE_STORE;
  840.                                 } else {
  841.                                         /*
  842.                                         **      Run command.
  843.                                         **/
  844.                                         ( rco->rc_Func )( ra, NULL );
  845.                                         /*
  846.                                         **      Store results.
  847.                                         **/
  848.                                         r      = ra->ra_RC;
  849.                                         r2     = ra->ra_RC2;
  850.                                         result = ra->ra_Result;
  851.                                 }
  852.                                 /*
  853.                                 **      Deallocate the REXXARGS structure.
  854.                                 **/
  855.                                 FreeMemory( ra );
  856.                         } else
  857.                                 r2 = ERROR_NO_FREE_STORE;
  858.                         /*
  859.                         **      When not passed to the rexx server
  860.                         **      we must close the given IO handle
  861.                         **      ourselves.
  862.                         **/
  863.                         if ( acme->acme_IO ) Close( acme->acme_IO );
  864.                 } else {
  865.                         /*
  866.                         **      We do not send the new-line to
  867.                         **      the ARexx server.
  868.                         **/
  869.                         com[ strlen( com ) - 1 ] = '\0';
  870.                         /*
  871.                         **      Unknown commands are shipped
  872.                         **      off to the REXX server.
  873.                         **/
  874.                         if ( rxm = CreateRexxCommand( ad, com, acme->acme_IO )) {
  875.                                 if ( ! CommandToRexx( ad, rxm ))
  876.                                         r2 = ERROR_NOT_IMPLEMENTED;
  877.                                 else
  878.                                         r = r2 = 0L;
  879.                         } else
  880.                                 r2 = ERROR_NO_FREE_STORE;
  881.                 }
  882.                 /*
  883.                 **      Deallocate the command copy.
  884.                 **/
  885.                 FreeMemory( com );
  886.         } else
  887.                 r2 = ERROR_NO_FREE_STORE;
  888.  
  889.         /*
  890.         **      Put the results into their
  891.         **      storage spaces.
  892.         **/
  893.         if ( acme->acme_RC     ) *( acme->acme_RC     ) = r;
  894.         if ( acme->acme_RC2    ) *( acme->acme_RC2    ) = r2;
  895.         if ( acme->acme_Result ) *( acme->acme_Result ) = result;
  896.  
  897.         return( 1L );
  898. }
  899.  
  900. /*
  901. **      OM_GET.
  902. **/
  903. STATIC ULONG ARexxGet( Class *cl, Object *obj, struct opGet *opg )
  904. {
  905.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  906.         ULONG                   rc = 1L;
  907.  
  908.         /*
  909.         **      What do they want?
  910.         **/
  911.         switch ( opg->opg_AttrID ) {
  912.  
  913.                 case    AC_HostName:
  914.                         *( opg->opg_Storage ) = ( ULONG )ad->ad_HostName;
  915.                         break;
  916.  
  917.                 case    AC_RexxPortMask:
  918.                         *( opg->opg_Storage ) = ( 1L << ad->ad_Port->mp_SigBit );
  919.                         break;
  920.  
  921.                 default:
  922.                         rc = DoSuperMethodA( cl, obj, ( Msg )opg );
  923.                         break;
  924.         }
  925.         return( rc );
  926. }
  927.  
  928. /*
  929. **      ACM_HANDLE_EVENT.
  930. **/
  931. STATIC ULONG ARexxHandleEvent( Class *cl, Object *obj, Msg msg )
  932. {
  933.         struct RexxMsg          *rxm, *org;
  934.         AD                      *ad = ( AD * )INST_DATA( cl, obj );
  935.         ULONG                    rc = 1L;
  936.  
  937.         /*
  938.         **      Get the messages from the port.
  939.         **/
  940.         while ( rxm = ( struct RexxMsg * )GetMsg( ad->ad_Port )) {
  941.                 /*
  942.                 **      A Rexx command?
  943.                 **/
  944.                 if (( rxm->rm_Action & RXCODEMASK ) != RXCOMM )
  945.                         ReplyMsg(( struct Message * )rxm );
  946.                 else if ( rxm->rm_Node.mn_Node.ln_Type == NT_REPLYMSG ) {
  947.                         /*
  948.                         **      Reply'd message. See if it was started
  949.                         **      as a script.
  950.                         **/
  951.                         if ( org = ( struct RexxMsg * )rxm->rm_Args[ 15 ] ) {
  952.                                 if ( rxm->rm_Result1 )
  953.                                         ReplyRexxCommand( org, 20, ERROR_NOT_IMPLEMENTED, NULL );
  954.                                 else
  955.                                         ReplyRexxCommand( org, 0, 0, ( UBYTE * )rxm->rm_Result2 );
  956.                         }
  957.                         /*
  958.                         **      Free the message and decrease the
  959.                         **      pending counter.
  960.                         **/
  961.                         FreeRexxCommand( rxm );
  962.                         ad->ad_PendCnt--;
  963.                 } else if ( ARG0( rxm ))
  964.                         /*
  965.                         **      Execute message.
  966.                         **/
  967.                         DoRXCommand( ad, rxm );
  968.                 else
  969.                         ReplyMsg(( struct Message * )rxm );
  970.         }
  971. }
  972.  
  973. /*
  974. **      Class dispatcher.
  975. **/
  976. STATIC SAVEDS ASM ULONG ARexxDispatch( REG(A0) Class *cl, REG(A2) Object *obj, REG(A1) Msg msg )
  977. {
  978.         ULONG                   rc = 0L;
  979.  
  980.         /*
  981.         **      Evaluate the method.
  982.         **/
  983.         switch ( msg->MethodID ) {
  984.  
  985.                 case    OM_NEW:
  986.                         rc = ARexxNew( cl, obj, ( struct opSet * )msg );
  987.                         break;
  988.  
  989.                 case    OM_GET:
  990.                         rc = ARexxGet( cl, obj, ( struct opGet * )msg );
  991.                         break;
  992.  
  993.                 case    OM_DISPOSE:
  994.                         rc = ARexxDispose( cl, obj, msg );
  995.                         break;
  996.  
  997.                 case    ACM_HANDLE_EVENT:
  998.                         rc = ARexxHandleEvent( cl, obj, msg );
  999.                         break;
  1000.  
  1001.                 case    ACM_EXECUTE:
  1002.                         rc = ARexxExecute( cl, obj, ( struct acmExecute * )msg );
  1003.                         break;
  1004.  
  1005.                 default:
  1006.                         rc = DoSuperMethodA( cl, obj, msg );
  1007.                         break;
  1008.         }
  1009.         return ( rc );
  1010. }
  1011.